<?php

/*
 * This file is part of the php-phantomjs.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Ling\PhantomJs\Procedure;

use Symfony\Component\Config\FileLocatorInterface;
use Ling\PhantomJs\Exception\NotExistsException;

/**
 * PHP PhantomJs
 *
 * @author Jon Wenmoth <contact@jonnyw.me>
 */
class ProcedureLoader implements ProcedureLoaderInterface
{
    /**
     * Procedure factory.
     *
     * @var ProcedureFactoryInterface
     * @access protected
     */
    protected ProcedureFactoryInterface $procedureFactory;

    /**
     * File locator.
     *
     * @var FileLocatorInterface
     * @access protected
     */
    protected FileLocatorInterface $locator;

    /**
     * Internal constructor.
     *
     * @access public
     * @param ProcedureFactoryInterface $procedureFactory
     * @param FileLocatorInterface $locator
     */
    public function __construct(ProcedureFactoryInterface $procedureFactory, FileLocatorInterface $locator)
    {
        $this->procedureFactory = $procedureFactory;
        $this->locator = $locator;
    }

    /**
     * Load procedure instance by id.
     *
     * @access public
     * @param string $id
     * @return ProcedureInterface
     * @throws NotExistsException
     */
    public function load(string $id): ProcedureInterface
    {
        $procedure = $this->procedureFactory->createProcedure();
        $procedure->setTemplate(
            $this->loadTemplate($id)
        );
        return $procedure;
    }

    /**
     * Load procedure template by id.
     *
     * @access public
     * @param string $id
     * @param string $extension (default: 'proc')
     * @return string
     * @throws NotExistsException
     */
    public function loadTemplate(string $id, string $extension = 'proc'): string
    {
        $path = $this->locator->locate(sprintf('%s.%s', $id, $extension));

        return $this->loadFile($path);
    }

    /**
     * Load procedure file content.
     *
     * @access protected
     * @param string $file
     * @return string
     * @throws \InvalidArgumentException
     * @throws NotExistsException
     */
    protected function loadFile(string $file): string
    {
        if (!stream_is_local($file)) {
            throw new \InvalidArgumentException(sprintf('Procedure file is not a local file: "%s"', $file));
        }

        if (!file_exists($file)) {
            throw new NotExistsException(sprintf('Procedure file does not exist: "%s"', $file));
        }

        return file_get_contents($file);
    }
}
